【GD32F427开发板试用】硬件SPI通信驱动CH376芯片,用单片机实现U盘数据下载 您所在的位置:网站首页 spi flash芯片 【GD32F427开发板试用】硬件SPI通信驱动CH376芯片,用单片机实现U盘数据下载

【GD32F427开发板试用】硬件SPI通信驱动CH376芯片,用单片机实现U盘数据下载

#【GD32F427开发板试用】硬件SPI通信驱动CH376芯片,用单片机实现U盘数据下载| 来源: 网络整理| 查看: 265

本篇文章来自极术社区与兆易创新组织的GD32F427开发板评测活动,更多开发板试用活动请关注极术社区网站。作者:周文杰

SPI通信作为单片机多种基础数据传输模式中的一种,驱动外部芯片CH376实现数据导出到U盘功能在实际工程项目中是很方便的。本文提供了GD32F427驱动CH376实现数据从U盘导出的完整硬件原理图和软件程序。

硬件连接方面

软件程序方面

SPI0的GPIO引脚初始化

void gpio_config(void) { /* configure SPI0 GPIO */ gpio_af_set(GPIOA, GPIO_AF_5, GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7); gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7); gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7); /* set SPI1_NSS as GPIO*/ gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_4); gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_4); gpio_init(GPIOB, GPIO_MODE_IPU , GPIO_OSPEED_50MHZ, GPIO_PIN_0);//PB0配置成上拉输入 }

SPI0的配置初始化

void spi_config(void) { spi_parameter_struct spi_init_struct; /* configure SPI1 parameter */ spi_init_struct.trans_mode = SPI_TRANSMODE_FULLDUPLEX; spi_init_struct.device_mode = SPI_MASTER;; spi_init_struct.frame_size = SPI_FRAMESIZE_8BIT;; spi_init_struct.clock_polarity_phase = SPI_CK_PL_LOW_PH_2EDGE; spi_init_struct.nss = SPI_NSS_SOFT; spi_init_struct.prescale = SPI_PSC_32; spi_init_struct.endian = SPI_ENDIAN_MSB;; spi_init(SPI0, &spi_init_struct); }

SPI0的数据发送函数

uint8_t spi0_send_byte(uint8_t spi_byte) { uint8_t ByteSend,ByteRecv; ByteSend=spi_byte; while(RESET == spi_i2s_flag_get(SPI0, SPI_FLAG_TBE)); spi_i2s_data_transmit(SPI0,ByteSend); while(RESET == spi_i2s_flag_get(SPI0, SPI_FLAG_RBNE)); ByteRecv=spi_i2s_data_receive(SPI0); return ByteRecv; }

CH376芯片的驱动程序文件为bsp_ch376.c何bsp_ch376.h。便于工程移植使用。bsp_ch376.c

#ifndef BSP_CH376_H #define BSP_CH376_H #include "bsp_ch376.h" #include "gd32f30x_rcu.h" #include "gd32f30x_gpio.h" #include "systick.h" #include "gd32f30x.h" #include "uart3dma.h"//调试用 #include "bsp_spi.h" #define FLASH_CS_0() {gpio_bit_write(GPIOA, GPIO_PIN_4,RESET);delay_1ms(10);} #define FLASH_CS_1() {gpio_bit_write(GPIOA, GPIO_PIN_4,SET);delay_1ms(10);} #define CH376_INTPORT GPIOB //定义IO接口 #define CH376_INT GPIO_PIN_0 //定义IO接口【此处是预留引脚,程序中未使用】 uint8_t retval = 0; //返回值 uint32_t u32retcount = 0; //写入字节数 uint32_t u32count = 0; //循环变量 char retString[120]=""; char buf[512]=""; void xWriteCH376Cmd(uint8_t mCmd){ FLASH_CS_1(); /* 防止之前未通过xEndCH376Cmd禁止SPI片选 */ delay_1us(20); /* 对于双向I/O引脚模拟SPI接口,那么必须确保已经设置SPI_SCS,SPI_SCK,SPI_SDI为输出 * 方向,SPI_SDO为输入方向 */ FLASH_CS_0(); /* SPI片选有效 */ spi0_send_byte( mCmd ); /* 发出命令码 */ delay_1us(1800); /* 延时1.5mS确保读写周期大于1.5mS,或者用上面一行的状态查询代替 */ } void xWriteCH376Data(uint8_t mData){ spi0_send_byte( mData ); delay_1us(700); /* 确保读写周期大于0.6mS */ } uint8_t xReadCH376Data(void){ uint8_t i; delay_1us(20); i = spi0_send_byte(0xFF); return(i); } void xEndCH376Cmd(void){ //结束命令 FLASH_CS_1(); //SPI片选无效,结束CH376命令 } /******************************************************************************* * 描 述 : 查询CH376中断(INT#低电平). * 返 回 : 0:无中断. 1:有中断. ****************************************************************************** uint8_t Query376Interrupt(void){ uint8_t i; i = gpio_input_bit_get(CH376_INTPORT,CH376_INT); return( i == 0); } */ /******************************************************************************* * 描 述 : 初始化CH376. * 返 回 : FALSE:无中断. TRUE:有中断. *******************************************************************************/ uint8_t mInitCH376Host(void){ uint8_t u8ret; delay_1ms(600); FLASH_CS_1(); xWriteCH376Cmd( CMD11_CHECK_EXIST ); /* 测试单片机与CH376之间的通讯接口 */ xWriteCH376Data( 0x55 ); u8ret = xReadCH376Data( ); // printf("res =%02x \n",(unsigned short)res); xEndCH376Cmd( ); if ( u8ret != 0xAA ) return( ERR_USB_UNKNOWN ); /* 通讯接口不正常,可能原因有:接口连接异常,其它设备影响(片选不唯一),串口波特率,一直在复位,晶振不工作 */ xWriteCH376Cmd( CMD11_SET_USB_MODE ); /* 设备USB工作模式 */ xWriteCH376Data( 0x06 ); //06H=已启用的主机方式并且自动产生SOF包 delay_1ms(1); u8ret = xReadCH376Data( ); // printf("res =%02x \n",(unsigned short)res); xEndCH376Cmd( ); if ( u8ret == CMD_RET_SUCCESS ){ //RES=51 命令操作成功 UART3_Transmit_DMA(UART3,"#########################################################ok", 200); return( USB_INT_SUCCESS ); //USB事务或者传输操作成功 }else{ UART3_Transmit_DMA(UART3,"not ok", 20); return( ERR_USB_UNKNOWN );/* 设置模式错误 */ } } /******************************************************************************* * 描 述 : 查询CH376中断(INT#低电平). * 返 回 : 0:无中断. 1:有中断. *******************************************************************************/ uint8_t Query376Interrupt(void){ uint8_t i; char strings[200]=""; i = gpio_input_bit_get(CH376_INTPORT, GPIO_PIN_0); //i=~i; //sprintf(strings, "%x\n", i); //UART3_Transmit_DMA(UART3,(uint8_t *)strings, 10); return ( i == 0x00 ); } /******************************************************************************* * 函 数 名 : CH376GetIntStatus * 描 述 : 获取中断状态并取消中断请求. * 输 入 : 无. * 返 回 : UINT8 s: * 中断状态. *******************************************************************************/ uint8_t CH376GetIntStatus( void ) { uint8_t s; xWriteCH376Cmd( CMD01_GET_STATUS ); s = xReadCH376Data( ); xEndCH376Cmd( ); return( s ); } uint8_t Wait376Interrupt( void ) { /* 是否定义了超时时间 */ uint32_t i; uint8_t ret=0; for ( i = 0; i < 50000; i ++ ) /* 计数防止超时,默认的超时时间,与单片机主频有关 */ { ret = Query376Interrupt() ; if (ret) { return( CH376GetIntStatus()); /* 检测到中断 */ } /* 在等待CH376中断的过程中,可以做些需要及时处理的其它事情 */ } return( ERR_USB_UNKNOWN ); /* 不应该发生的情况 */ } uint8_t CH376SendCmdWaitInt( uint8_t mCmd ) { xWriteCH376Cmd( mCmd ); xEndCH376Cmd( ); return( Wait376Interrupt( ) ); } /******************************************************************************* * 函 数 名 : CH376SendCmdDatWaitInt * 描 述 : 发出命令码和一字节数据后,等待中断. * 输 入 : 无. * 返 回 : 中断状态. *******************************************************************************/ uint8_t CH376SendCmdDatWaitInt( uint8_t mCmd, uint8_t mDat ) { xWriteCH376Cmd( mCmd ); xWriteCH376Data( mDat ); xEndCH376Cmd( ); return( Wait376Interrupt( ) ); } /******************************************************************************* * 函 数 名 : CH376ReadVar8 * 描 述 : 读CH376芯片内部的8位变量. * 输 入 : 无. * 返 回 : 8位变量. *******************************************************************************/ uint8_t CH376ReadVar8( uint8_t var ) { uint8_t c0; xWriteCH376Cmd( CMD11_READ_VAR8 ); /* 读取指定的8位文件系统变量 */ xWriteCH376Data( var ); c0 = xReadCH376Data( ); xEndCH376Cmd( ); return( c0 ); } #define VAR_DISK_STATUS 0x2B /* 主机文件模式下的磁盘及文件状态 */ /******************************************************************************* * 函 数 名 : CH376GetDiskStatus * 描 述 : 获取磁盘和文件系统的工作状态. * 输 入 : 无. * 返 回 : 状态. *******************************************************************************/ uint8_t CH376GetDiskStatus( void ) { return( CH376ReadVar8( VAR_DISK_STATUS ) ); } /******************************************************************************* * 函 数 名 : CH376FileClose * 描 述 : 关闭当前已经打开的文件或者目录(文件夹) * 输 入 : PUINT8 UpdateSz: * 是否更新文件长度. * 返 回 : 中断状态. *******************************************************************************/ uint8_t CH376FileClose( uint8_t UpdateSz ) { return( CH376SendCmdDatWaitInt( CMD1H_FILE_CLOSE, UpdateSz ) ); } /******************************************************************************* * 函 数 名 : CH376DiskMount * 描 述 : 初始化磁盘并测试磁盘是否就绪. * 输 入 : 无. * 返 回 : 中断状态. *******************************************************************************/ uint8_t CH376DiskMount( void ) { return( CH376SendCmdWaitInt( 0x31 ) ); /* 初始化磁盘并测试磁盘是否就绪 */ } /******************************************************************************* * 函 数 名 : CH376WriteReqBlock * 描 述 : 向内部指定缓冲区写入请求的数据块,返回长度. * 输 入 : PUINT8 buf: * 指向发送缓冲区. * 返 回 : UINT8 s:后续数据长度. *******************************************************************************/ uint8_t CH376WriteReqBlock( uint8_t * buf ){ uint8_t s, l; xWriteCH376Cmd( CMD01_WR_REQ_DATA ); /* 向内部指定缓冲区写入请求的数据块 */ s = l = xReadCH376Data( ); /* 后续数据长度 */ if ( l ) { do { xWriteCH376Data( *buf ); buf ++; } while ( -- l ); } xEndCH376Cmd( ); return( s ); } /******************************************************************************* * 函 数 名 : CH376ByteLocate * 描 述 : 以字节为单位移动当前文件指针 * 输 入 : UINT32 offset: * 指针偏移地址. * 返 回 : 中断状态. *******************************************************************************/ uint8_t CH376ByteLocate( uint32_t offset ) { xWriteCH376Cmd( CMD4H_BYTE_LOCATE ); xWriteCH376Data( (uint8_t)offset ); xWriteCH376Data( (uint8_t)((uint16_t)offset>>8) ); xWriteCH376Data( (uint8_t)(offset>>16) ); xWriteCH376Data( (uint8_t)(offset>>24) ); xEndCH376Cmd( ); return( Wait376Interrupt( ) ); } /******************************************************************************* * 函 数 名 : CH376ByteWrite * 描 述 : 以字节为单位向当前位置写入数据块. * 输 入 : PUINT8 buf: * 指向外部缓冲区. * UINT16 ReqCount: * 请求写入的字节数. * PUINT16 RealCount: * 实际写入的字节数. * 返 回 : 中断状态. *******************************************************************************/ uint8_t CH376ByteWrite( uint8_t * buf, uint16_t ReqCount, uint16_t * RealCount ) { uint8_t s; xWriteCH376Cmd( CMD2H_BYTE_WRITE ); xWriteCH376Data( (uint8_t)ReqCount ); xWriteCH376Data( (uint8_t)(ReqCount>>8) ); xEndCH376Cmd( ); if ( RealCount ) { *RealCount = 0; } while ( 1 ) { s = Wait376Interrupt( ); if ( s == USB_INT_DISK_WRITE ) { s = CH376WriteReqBlock( buf ); /* 向内部指定缓冲区写入请求的数据块,返回长度 */ xWriteCH376Cmd( CMD0H_BYTE_WR_GO ); xEndCH376Cmd( ); buf += s; if ( RealCount ) *RealCount += s; } else { return( s ); /* 错误 */ } } } /******************************************************************************* * 函 数 名 : CH376Read32bitDat * 描 述 : 从CH376芯片读取32位的数据并结束命令. * 输 入 : 无. * 返 回 : 32位数据. *******************************************************************************/ uint32_t CH376Read32bitDat( void ) { uint8_t c0, c1, c2, c3; c0 = xReadCH376Data( ); c1 = xReadCH376Data( ); c2 = xReadCH376Data( ); c3 = xReadCH376Data( ); xEndCH376Cmd( ); return( c0 | (uint16_t)c1 > 16 ) ); xWriteCH376Data( (uint8_t)( dat >> 24 ) ); xEndCH376Cmd( ); } /******************************************************************************* * 函 数 名 : CH376SetFileName * 描 述 : 设置将要操作的文件的文件名 . * 输 入 : PUINT8 name: * 指向文件名缓冲区. * 返 回 : 无. *******************************************************************************/ void CH376SetFileName( uint8_t * name ) { uint8_t c; #ifndef DEF_IC_V43_U /* 默认支持低版本 */ uint8_t s; xWriteCH376Cmd( CMD01_GET_IC_VER ); /* 获取芯片版本 */ if ( xReadCH376Data( ) < 0x43 ) { if ( CH376ReadVar8( VAR_DISK_STATUS ) < DEF_DISK_READY ) { xWriteCH376Cmd( CMD10_SET_FILE_NAME ); xWriteCH376Data( 0 ); s = CH376SendCmdWaitInt( CMD0H_FILE_OPEN ); if ( s == USB_INT_SUCCESS ) { s = CH376ReadVar8( 0xCF ); if ( s ) { CH376WriteVar32( 0x4C, CH376ReadVar32( 0x4C ) + ( (uint16_t)s = 5 ) // 有的U盘总是返回未准备好,不过可以忽略,只要其建立连接MOUNTED且尝试5*50mS { //UART3_Transmit_DMA(UART3,(uint8_t *)"STATUSOK", 10); break; } } delay_1ms(1); //每次操作后必要的延时 } /******************************************************************************* * 函 数 名 : CH376_INIT * 描 述 : CH376初始化. U盘操作之前第一步 * 输 入 : filename 类型 uint8_t * * 返 回 : USB_INT_SUCCESS 代表U盘已经准备好 *******************************************************************************/ uint8_t CH376_OPEN( uint8_t * filename ) { uint32_t u32retcount = 0; u32retcount=CH376FileOpenPath( filename ); /* 打开已存在的文件 */ if(u32retcount==ERR_MISS_FILE ){ u32retcount=CH376FileCreatePath(filename ); /* 文件不存在则创建 */ } u32retcount = CH376ByteLocate( 0xFFFFFFFF ); /* 移动文件指针 0xFFFFFFFF 到最后 */ if ( u32retcount != USB_INT_SUCCESS ) { return( u32retcount ); } } #endif /* BSP_CH376_H */

bsp_ch376.h

#ifndef BSP_CH376_H #define BSP_CH376_H //#include "sys.h" #include "gd32f30x.h" #include "bsp_spi.h" #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif #ifndef NULL #define NULL 0 #endif //#define SPI2PORT GPIOB // //#define SPI2_MOSI GPIO_PIN_15 // //#define SPI2_MISO GPIO_PIN_14 // //#define SPI2_SCK GPIO_PIN_13 // //#define SPI2_NSS GPIO_PIN_12 // #define CH376_INTPORT GPIOB //定义IO接口 #define CH376_INT GPIO_PIN_0 //定义IO接口【此处是预留引脚,程序中未使用】 /* 硬件特性 */ #define CH376_DAT_BLOCK_LEN 0x40 /* USB单个数据包, 数据块的最大长度, 默认缓冲区的长度 */ extern uint8_t retval ; //返回值 extern uint32_t u32retcount; //写入字节数 extern uint32_t u32count; //循环变量 extern char retString[120]; extern char buf[512]; /* ********************************************************************************************************************* */ /* 命令代码 */ /* 部分命令兼容CH375芯片, 但是输入数据或者输出数据的可能局部不同) */ /* 一个命令操作顺序包含: 一个命令码(对于串口方式,命令码之前还需要两个同步码), 若干个输入数据(可以是0个), 产生中断通知 或者 若干个输出数据(可以是0个), 二选一, 有中断通知则一定没有输出数据, 有输出数据则一定不产生中断 仅CMD01_WR_REQ_DATA命令例外, 顺序包含: 一个命令码, 一个输出数据, 若干个输入数据 命令码起名规则: CMDxy_NAME 其中的x和y都是数字, x说明最少输入数据个数(字节数), y说明最少输出数据个数(字节数), y如果是H则说明产生中断通知, 有些命令能够实现0到多个字节的数据块读写, 数据块本身的字节数未包含在上述x或y之内 */ /* 本文件默认会同时提供与CH375芯片命令码兼容的命令码格式(即去掉x和y之后), 如果不需要, 那么可以定义_NO_CH375_COMPATIBLE_禁止 */ /* ********************************************************************************************************************* */ /* 主要命令(手册一), 常用 */ #define CMD01_GET_IC_VER 0x01 /* 获取芯片及固件版本 */ /* 输出: 版本号( 位7为0, 位6为1, 位5~位0为版本号 ) */ /* CH376返回版本号的值为041H即版本号为01H */ #define CMD21_SET_BAUDRATE 0x02 /* 串口方式: 设置串口通讯波特率(上电或者复位后的默认波特率为9600bps,由D4/D5/D6引脚选择) */ /* 输入: 波特率分频系数, 波特率分频常数 */ /* 输出: 操作状态( CMD_RET_SUCCESS或CMD_RET_ABORT, 其它值说明操作未完成 ) */ #define CMD00_ENTER_SLEEP 0x03 /* 进入睡眠状态 */ #define CMD00_RESET_ALL 0x05 /* 执行硬件复位 */ #define CMD11_CHECK_EXIST 0x06 /* 测试通讯接口和工作状态 */ /* 输入: 任意数据 */ /* 输出: 输入数据的按位取反 */ #define CMD20_CHK_SUSPEND 0x0B /* 设备方式: 设置检查USB总线挂起状态的方式 */ /* 输入: 数据10H, 检查方式 */ /* 00H=不检查USB挂起, 04H=以50mS为间隔检查USB挂起, 05H=以10mS为间隔检查USB挂起 */ #define CMD20_SET_SDO_INT 0x0B /* SPI接口方式: 设置SPI的SDO引脚的中断方式 */ /* 输入: 数据16H, 中断方式 */ /* 10H=禁止SDO引脚用于中断输出,在SCS片选无效时三态输出禁止, 90H=SDO引脚在SCS片选无效时兼做中断请求输出 */ #define CMD14_GET_FILE_SIZE 0x0C /* 主机文件模式: 获取当前文件长度 */ /* 输入: 数据68H */ /* 输出: 当前文件长度(总长度32位,低字节在前) */ #define CMD50_SET_FILE_SIZE 0x0D /* 主机文件模式: 设置当前文件长度 */ /* 输入: 数据68H, 当前文件长度(总长度32位,低字节在前) */ #define CMD11_SET_USB_MODE 0x15 /* 设置USB工作模式 */ //00H=未启用的设备方式, 01H=已启用的设备方式并且使用外部固件模式(串口不支持), //02H=已启用的设备方式并且使用内置固件模式 03H=SD卡主机模式/未启用的主机模式,用于管理和存取SD卡中的文件 //04H=未启用的主机方式, 05H=已启用的主机方式, 06H=已启用的主机方式并且自动产生SOF包, 07H=已启用的主机方式并且复位USB总线 */ //输出: 操作状态( CMD_RET_SUCCESS或CMD_RET_ABORT, 其它值说明操作未完成 ) #define CMD01_GET_STATUS 0x22 /* 获取中断状态并取消中断请求 */ /* 输出: 中断状态 */ #define CMD00_UNLOCK_USB 0x23 /* 设备方式: 释放当前USB缓冲区 */ #define CMD01_RD_USB_DATA0 0x27 /* 从当前USB中断的端点缓冲区或者主机端点的接收缓冲区读取数据块 */ /* 输出: 长度, 数据流 */ #define CMD01_RD_USB_DATA 0x28 /* 设备方式: 从当前USB中断的端点缓冲区读取数据块, 并释放缓冲区, 相当于 CMD01_RD_USB_DATA0 + CMD00_UNLOCK_USB */ /* 输出: 长度, 数据流 */ #define CMD10_WR_USB_DATA7 0x2B /* 设备方式: 向USB端点2的发送缓冲区写入数据块 */ /* 输入: 长度, 数据流 */ #define CMD10_WR_HOST_DATA 0x2C /* 向USB主机端点的发送缓冲区写入数据块 */ /* 输入: 长度, 数据流 */ #define CMD01_WR_REQ_DATA 0x2D /* 向内部指定缓冲区写入请求的数据块 */ /* 输出: 长度 */ /* 输入: 数据流 */ #define CMD20_WR_OFS_DATA 0x2E /* 向内部缓冲区指定偏移地址写入数据块 */ /* 输入: 偏移, 长度, 数据流 */ #define CMD10_SET_FILE_NAME 0x2F /* 主机文件模式: 设置将要操作的文件的文件名 */ /* 输入: 以0结束的字符串(含结束符0在内长度不超过14个字符) */ /* ********************************************************************************************************************* */ /* 主要命令(手册一), 常用, 以下命令总是在操作结束时产生中断通知, 并且总是没有输出数据 */ #define CMD0H_DISK_CONNECT 0x30 /* 主机文件模式/不支持SD卡: 检查磁盘是否连接 */ /* 输出中断 */ #define CMD0H_DISK_MOUNT 0x31 /* 主机文件模式: 初始化磁盘并测试磁盘是否就绪 */ /* 输出中断 */ #define CMD0H_FILE_OPEN 0x32 /* 主机文件模式: 打开文件或者目录(文件夹),或者枚举文件和目录(文件夹) */ /* 输出中断 */ #define CMD0H_FILE_ENUM_GO 0x33 /* 主机文件模式: 继续枚举文件和目录(文件夹) */ /* 输出中断 */ #define CMD0H_FILE_CREATE 0x34 /* 主机文件模式: 新建文件,如果文件已经存在那么先删除 */ /* 输出中断 */ #define CMD0H_FILE_ERASE 0x35 /* 主机文件模式: 删除文件,如果已经打开则直接删除,否则对于文件会先打开再删除,子目录必须先打开 */ /* 输出中断 */ #define CMD1H_FILE_CLOSE 0x36 /* 主机文件模式: 关闭当前已经打开的文件或者目录(文件夹) */ /* 输入: 是否允许更新文件长度 */ /* 00H=禁止更新长度, 01H=允许更新长度 */ /* 输出中断 */ #define CMD1H_DIR_INFO_READ 0x37 /* 主机文件模式: 读取文件的目录信息 */ /* 输入: 指定需要读取的目录信息结构在扇区内的索引号 */ /* 索引号范围为00H~0FH, 索引号0FFH则为当前已经打开的文件 */ /* 输出中断 */ #define CMD0H_DIR_INFO_SAVE 0x38 /* 主机文件模式: 保存文件的目录信息 */ /* 输出中断 */ #define CMD4H_BYTE_LOCATE 0x39 /* 主机文件模式: 以字节为单位移动当前文件指针 */ /* 输入: 偏移字节数(总长度32位,低字节在前) */ /* 输出中断 */ #define CMD2H_BYTE_READ 0x3A /* 主机文件模式: 以字节为单位从当前位置读取数据块 */ /* 输入: 请求读取的字节数(总长度16位,低字节在前) */ /* 输出中断 */ #define CMD0H_BYTE_RD_GO 0x3B /* 主机文件模式: 继续字节读 */ /* 输出中断 */ #define CMD2H_BYTE_WRITE 0x3C /* 主机文件模式: 以字节为单位向当前位置写入数据块 */ /* 输入: 请求写入的字节数(总长度16位,低字节在前) */ /* 输出中断 */ #define CMD0H_BYTE_WR_GO 0x3D /* 主机文件模式: 继续字节写 */ /* 输出中断 */ #define CMD0H_DISK_CAPACITY 0x3E /* 主机文件模式: 查询磁盘物理容量 */ /* 输出中断 */ #define CMD0H_DISK_QUERY 0x3F /* 主机文件模式: 查询磁盘空间信息 */ /* 输出中断 */ #define CMD0H_DIR_CREATE 0x40 /* 主机文件模式: 新建目录(文件夹)并打开,如果目录已经存在那么直接打开 */ /* 输出中断 */ #define CMD4H_SEC_LOCATE 0x4A /* 主机文件模式: 以扇区为单位移动当前文件指针 */ /* 输入: 偏移扇区数(总长度32位,低字节在前) */ /* 输出中断 */ #define CMD1H_SEC_READ 0x4B /* 主机文件模式/不支持SD卡: 以扇区为单位从当前位置读取数据块 */ /* 输入: 请求读取的扇区数 */ /* 输出中断 */ #define CMD1H_SEC_WRITE 0x4C /* 主机文件模式/不支持SD卡: 以扇区为单位在当前位置写入数据块 */ /* 输入: 请求写入的扇区数 */ /* 输出中断 */ #define CMD0H_DISK_BOC_CMD 0x50 /* 主机方式/不支持SD卡: 对USB存储器执行BulkOnly传输协议的命令 */ /* 输出中断 */ #define CMD5H_DISK_READ 0x54 /* 主机方式/不支持SD卡: 从USB存储器读物理扇区 */ /* 输入: LBA物理扇区地址(总长度32位, 低字节在前), 扇区数(01H~FFH) */ /* 输出中断 */ #define CMD0H_DISK_RD_GO 0x55 /* 主机方式/不支持SD卡: 继续执行USB存储器的物理扇区读操作 */ /* 输出中断 */ #define CMD5H_DISK_WRITE 0x56 /* 主机方式/不支持SD卡: 向USB存储器写物理扇区 */ /* 输入: LBA物理扇区地址(总长度32位, 低字节在前), 扇区数(01H~FFH) */ /* 输出中断 */ #define CMD0H_DISK_WR_GO 0x57 /* 主机方式/不支持SD卡: 继续执行USB存储器的物理扇区写操作 */ /* 输出中断 */ /* ********************************************************************************************************************* */ /* 辅助命令(手册二), 不太常用或者是为了与CH375和CH372兼容 */ #define CMD10_SET_USB_SPEED 0x04 /* 设置USB总线速度, 在每次CMD11_SET_USB_MODE设置USB工作模式时会自动恢复到12Mbps全速 */ /* 输入: 总线速度代码 */ /* 00H=12Mbps全速FullSpeed(默认值), 01H=1.5Mbps(仅修改频率), 02H=1.5Mbps低速LowSpeed */ #define CMD11_GET_DEV_RATE 0x0A /* 主机方式: 获取当前连接的USB设备的数据速率类型 */ /* 输入: 数据07H */ /* 输出: 数据速率类型 */ /* 位4为1则是1.5Mbps低速USB设备, 否则是12Mbps全速USB设备 */ #define CMD11_GET_TOGGLE 0x0A /* 获取OUT事务的同步状态 */ /* 输入: 数据1AH */ /* 输出: 同步状态 */ /* 位4为1则OUT事务同步, 否则OUT事务不同步 */ #define CMD11_READ_VAR8 0x0A /* 读取指定的8位文件系统变量 */ /* 输入: 变量地址 */ /* 输出: 数据 */ /*#define CMD11_GET_MAX_LUN = CMD11_READ_VAR8( VAR_UDISK_LUN )*/ /* 主机方式: 获取USB存储器最大和当前逻辑单元号 */ #define CMD20_SET_RETRY 0x0B /* 主机方式: 设置USB事务操作的重试次数 */ /* 输入: 数据25H, 重试次数 */ /* 位7为0则收到NAK时不重试, 位7为1位6为0则收到NAK时无限重试, 位7为1位6为1则收到NAK时最多重试3秒, 位5~位0为超时后的重试次数 */ #define CMD20_WRITE_VAR8 0x0B /* 设置指定的8位文件系统变量 */ /* 输入: 变量地址, 数据 */ /*#define CMD20_SET_DISK_LUN = CMD20_WRITE_VAR8( VAR_UDISK_LUN )*/ /* 主机方式: 设置USB存储器的当前逻辑单元号 */ #define CMD14_READ_VAR32 0x0C /* 读取指定的32位文件系统变量 */ /* 输入: 变量地址 */ /* 输出: 数据(总长度32位,低字节在前) */ #define CMD50_WRITE_VAR32 0x0D /* 设置指定的32位文件系统变量 */ /* 输入: 变量地址, 数据(总长度32位,低字节在前) */ #define CMD01_DELAY_100US 0x0F /* 延时100uS(串口不支持) */ /* 输出: 延时期间输出0,延时结束输出非0 */ #define CMD40_SET_USB_ID 0x12 /* 设备方式: 设置USB厂商VID和产品PID */ /* 输入: 厂商ID低字节, 厂商ID高字节, 产品ID低字节, 产品ID高字节 */ #define CMD10_SET_USB_ADDR 0x13 /* 设置USB地址 */ /* 输入: 地址值 */ #define CMD01_TEST_CONNECT 0x16 /* 主机方式/不支持SD卡: 检查USB设备连接状态 */ /* 输出: 状态( USB_INT_CONNECT或USB_INT_DISCONNECT或USB_INT_USB_READY, 其它值说明操作未完成 ) */ #define CMD00_ABORT_NAK 0x17 /* 主机方式: 放弃当前NAK的重试 */ #define CMD10_SET_ENDP2 0x18 /* 设备方式(串口不支持): 设置USB端点0的接收器 */ /* 输入: 工作方式 */ /* 位7为1则位6为同步触发位, 否则同步触发位不变 */ /* 位3~位0为事务响应方式: 0000-就绪ACK, 1110-正忙NAK, 1111-错误STALL */ #define CMD10_SET_ENDP3 0x19 /* 设备方式(串口不支持): 设置USB端点0的发送器 */ /* 输入: 工作方式 */ /* 位7为1则位6为同步触发位, 否则同步触发位不变 */ /* 位3~位0为事务响应方式: 0000~1000-就绪ACK, 1110-正忙NAK, 1111-错误STALL */ #define CMD10_SET_ENDP4 0x1A /* 设备方式(串口不支持): 设置USB端点1的接收器 */ /* 输入: 工作方式 */ /* 位7为1则位6为同步触发位, 否则同步触发位不变 */ /* 位3~位0为事务响应方式: 0000-就绪ACK, 1110-正忙NAK, 1111-错误STALL */ #define CMD10_SET_ENDP5 0x1B /* 设备方式(串口不支持): 设置USB端点1的发送器 */ /* 输入: 工作方式 */ /* 位7为1则位6为同步触发位, 否则同步触发位不变 */ /* 位3~位0为事务响应方式: 0000~1000-就绪ACK, 1110-正忙NAK, 1111-错误STALL */ #define CMD10_SET_ENDP6 0x1C /* 设置USB端点2/主机端点的接收器 */ /* 输入: 工作方式 */ /* 位7为1则位6为同步触发位, 否则同步触发位不变 */ /* 位3~位0为事务响应方式: 0000-就绪ACK, 1101-就绪但不返回ACK, 1110-正忙NAK, 1111-错误STALL */ #define CMD10_SET_ENDP7 0x1D /* 设置USB端点2/主机端点的发送器 */ /* 输入: 工作方式 */ /* 位7为1则位6为同步触发位, 否则同步触发位不变 */ /* 位3~位0为事务响应方式: 0000-就绪ACK, 1101-就绪但无须应答, 1110-正忙NAK, 1111-错误STALL */ #define CMD00_DIRTY_BUFFER 0x25 /* 主机文件模式: 清除内部的磁盘和文件缓冲区 */ #define CMD10_WR_USB_DATA3 0x29 /* 设备方式(串口不支持): 向USB端点0的发送缓冲区写入数据块 */ /* 输入: 长度, 数据流 */ #define CMD10_WR_USB_DATA5 0x2A /* 设备方式(串口不支持): 向USB端点1的发送缓冲区写入数据块 */ /* 输入: 长度, 数据流 */ /* ********************************************************************************************************************* */ /* 辅助命令(手册二), 不太常用或者是为了与CH375和CH372兼容, 以下命令总是在操作结束时产生中断通知, 并且总是没有输出数据 */ #define CMD1H_CLR_STALL 0x41 /* 主机方式: 控制传输-清除端点错误 */ /* 输入: 端点号 */ /* 输出中断 */ #define CMD1H_SET_ADDRESS 0x45 /* 主机方式: 控制传输-设置USB地址 */ /* 输入: 地址值 */ /* 输出中断 */ #define CMD1H_GET_DESCR 0x46 /* 主机方式: 控制传输-获取描述符 */ /* 输入: 描述符类型 */ /* 输出中断 */ #define CMD1H_SET_CONFIG 0x49 /* 主机方式: 控制传输-设置USB配置 */ /* 输入: 配置值 */ /* 输出中断 */ #define CMD0H_AUTO_SETUP 0x4D /* 主机方式/不支持SD卡: 自动配置USB设备 */ /* 输出中断 */ #define CMD2H_ISSUE_TKN_X 0x4E /* 主机方式: 发出同步令牌, 执行事务, 该命令可代替 CMD10_SET_ENDP6/CMD10_SET_ENDP7 + CMD1H_ISSUE_TOKEN */ /* 输入: 同步标志, 事务属性 */ /* 同步标志的位7为主机端点IN的同步触发位, 位6为主机端点OUT的同步触发位, 位5~位0必须为0 */ /* 事务属性的低4位是令牌, 高4位是端点号 */ /* 输出中断 */ #define CMD1H_ISSUE_TOKEN 0x4F /* 主机方式: 发出令牌, 执行事务, 建议用CMD2H_ISSUE_TKN_X命令 */ /* 输入: 事务属性 */ /* 低4位是令牌, 高4位是端点号 */ /* 输出中断 */ #define CMD0H_DISK_INIT 0x51 /* 主机方式/不支持SD卡: 初始化USB存储器 */ /* 输出中断 */ #define CMD0H_DISK_RESET 0x52 /* 主机方式/不支持SD卡: 控制传输-复位USB存储器 */ /* 输出中断 */ #define CMD0H_DISK_SIZE 0x53 /* 主机方式/不支持SD卡: 获取USB存储器的容量 */ /* 输出中断 */ #define CMD0H_DISK_INQUIRY 0x58 /* 主机方式/不支持SD卡: 查询USB存储器特性 */ /* 输出中断 */ #define CMD0H_DISK_READY 0x59 /* 主机方式/不支持SD卡: 检查USB存储器就绪 */ /* 输出中断 */ #define CMD0H_DISK_R_SENSE 0x5A /* 主机方式/不支持SD卡: 检查USB存储器错误 */ /* 输出中断 */ #define CMD0H_RD_DISK_SEC 0x5B /* 主机文件模式: 从磁盘读取一个扇区的数据到内部缓冲区 */ /* 输出中断 */ #define CMD0H_WR_DISK_SEC 0x5C /* 主机文件模式: 将内部缓冲区的一个扇区的数据写入磁盘 */ /* 输出中断 */ #define CMD0H_DISK_MAX_LUN 0x5D /* 主机方式: 控制传输-获取USB存储器最大逻辑单元号 */ /* 输出中断 */ #define USB_INT_SUCCESS 0x14 /* USB事务或者传输操作成功 */ #define USB_INT_CONNECT 0x15 /* 检测到USB设备连接事件, 可能是新连接或者断开后重新连接 */ #define USB_INT_DISCONNECT 0x16 /* 检测到USB设备断开事件 */ #define USB_INT_BUF_OVER 0x17 /* USB传输的数据有误或者数据太多缓冲区溢出 */ #define USB_INT_USB_READY 0x18 /* USB设备已经被初始化(已经分配USB地址) */ #define USB_INT_DISK_READ 0x1D /* USB存储器请求数据读出 */ #define USB_INT_DISK_WRITE 0x1E /* USB存储器请求数据写入 */ #define USB_INT_DISK_ERR 0x1F /* USB存储器操作失败 */ /* 附加的USB操作状态定义 */ #define ERR_USB_UNKNOWN 0xFA /* 未知错误,不应该发生的情况,需检查硬件或者程序错误 */ #define CMD_RET_SUCCESS 0x51 /* 命令操作成功 */ #define CMD_RET_ABORT 0x5F /* 命令操作失败 */ //void SPI2_Init(void); //uint8_t SPI2_SendByte(uint8_t Byte); void xWriteCH376Cmd(uint8_t mCmd); void xWriteCH376Data(uint8_t mData); uint8_t xReadCH376Data(void); void xEndCH376Cmd(void); void spi0_init(void); uint8_t mInitCH376Host(void); uint8_t CH376DiskMount( void ); uint8_t CH376FileClose( uint8_t UpdateSz ); uint8_t CH376GetDiskStatus( void ); uint8_t CH376FileCreatePath( uint8_t * PathName ); uint8_t CH376ByteWrite( uint8_t * buf, uint16_t ReqCount, uint16_t * RealCount ); uint8_t CH376ByteLocate( uint32_t offset ); uint8_t CH376FileOpenPath( uint8_t * PathName ); #endif /* BSP_CH376_H */

main.c函数中调用实现数据导出到U盘的1234.txt文件

retval = mInitCH376Host(); retval = CH376DiskConnect(); //读出U盘的状态 if(retval == USB_INT_SUCCESS) { //检查U盘是否连接//等待U盘插入 UART3_Transmit_DMA(UART3,(uint8_t *)"U OK", 10);//------------------------------------------调试用 } else { UART3_Transmit_DMA(UART3,(uint8_t *)"没检测到U盘", 20);//------------------------------------调试用 } for ( u32count = 0; u32count < 10000; u32count ++ ) { delay_1ms( 10 ); retval = CH376DiskMount( ); //初始化磁盘并测试磁盘是否就绪. if ( retval == USB_INT_SUCCESS ) //准备好 { //UART3_Transmit_DMA(UART3,(uint8_t *)"INTOK", 10);//----------------------------------调试用 break; } else if ( retval == ERR_DISK_DISCON )// 检测到断开,重新检测并计时 { break; } if ( CH376GetDiskStatus( ) >= DEF_DISK_MOUNTED && u32count >= 5 ) // 有的U盘总是返回未准备好,不过可以忽略,只要其建立连接MOUNTED且尝试5*50mS { //UART3_Transmit_DMA(UART3,(uint8_t *)"STATUSOK", 10);//--------------------------------调试用 break; } } delay_1ms(1); //每次操作后必要的延时 u32retcount=CH376FileOpenPath( "/1234.TXT" ); if(u32retcount==ERR_MISS_FILE ){ u32retcount=CH376FileCreatePath( "/1234.TXT" ); } UART3_Transmit_DMA(UART3,(uint8_t *)"===\n", 20);//---------------------------------------------调试用 u32retcount = CH376ByteLocate( 0xFFFFFFFF ); if ( u32retcount != USB_INT_SUCCESS ) { return( u32retcount ); } delay_1ms(200); //每次操作后必要的延时 u32retcount = sprintf( (char *)buf , "时间 状态 \n"); u32retcount=CH376ByteWrite((uint8_t *) buf, u32retcount, NULL ); // 以字节为单位向当前位置写入数据块 for(u32count=0;u32count


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有